/* $Header: scc.c,v 2.2 01/10/02 10:33:02 przybyls Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME:  scc.c                                                 */
/* ============                                                        */
/*                                                                     */
/* Author:  Lesley Freed                                               */
/*                                                                     */
/* MODULE PURPOSE:  To define all functions used by single column      */
/*                  compensation and the test plot.  NOTE:  These      */
/*                  functions all run during the 512 Hz interrupt      */
/*                  so they are location in the SysCode memory section.*/
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/

#include <typedefs.h>
#include <p_wkfile.h>
#include <wkfile.h>
#include <ramps.h>
#include <zone_config.h>
#include <zone_status.h>
#include <status.h>
#include <error.h>
#include <sig_types.h>
#include <sigpath.h>

/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/


/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/


/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/


/*****************************/
/*   LOCAL DEFINES           */
/*****************************/



/***********************************************************************/
/* MACRO:  SUBTRACT_AND_CLAMP                                          */
/* ======                                                              */
/*                                                                     */
/* PURPOSE:  To perform and signed 32-bit subraction and clamp on      */
/*           underflow and overflow.                                   */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

#define SUBTRACT_AND_CLAMP( signal, value )                                    \
{                                                                              \
   if ( (signal) < 0 )                                                         \
   {                                                                           \
      (signal) -= (value);                                                     \
                                                                               \
      /* See if there was underflow */                                         \
      if ( ( (signal) >= 0 )  && ( (value) >= 0 ) )                            \
      {                                                                        \
         /* underflow occurred - the data has changed sign */                  \
         (signal) = (INT32)MIN_SIGNED_32BIT_VALUE;                             \
      }                                                                        \
   }                                                                           \
   else  /* signal >= 0 */                                                     \
   {                                                                           \
      (signal) -= (value);                                                     \
                                                                               \
      if ( ( (signal) < 0 )  && ( (value) < 0 ) )                              \
      {                                                                        \
         /* overflow occurred - the data has changed sign */                   \
         (signal) = MAX_SIGNED_32BIT_VALUE;                                    \
      }                                                                        \
   }                                                                           \
}




/***********************************************************************/
/* MACRO:  CALC_SCC_SLOPE                                              */
/* ======                                                              */
/*                                                                     */
/* PURPOSE:  To calculate the slope between two adjacent signal points */
/*           within a single column compensation (SCC) profile         */
/*                                                                     */
/*                                                                     */
/* RETURNED VALUE:  INT32 slope                                        */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:  none                                                        */
/*                                                                     */
/* LIMITATIONS:  This function assumes that the N past to it is        */
/*               non-zero.  If it is called with an N of zero you will */
/*               get a divide by zero.                                 */
/*                                                                     */
/***********************************************************************/



#define CALC_SCC_SLOPE( pccomp, N, i )                                         \
{                                                                              \
                                                                               \
   /*********************************************************************/     \
   /*                                                                   */     \
   /* Calculate the slope at a profile data point f(i) as follows:      */     \
   /*                                                                   */     \
   /* Average slope = f(i+1) - f(i-1)                                   */     \
   /*                 ---------------                                   */     \
   /*                     N1 + N2                                       */     \
   /*                                                                   */     \
   /* where N1 and N2 are the number of signals between f(i-1) and f(i) */     \
   /*       and f(i) and f(i+1)                                         */     \
   /*                                                                   */     \
   /*********************************************************************/     \
                                                                               \
   /* See if we are processing the first or last segment.  If so then we will*/\
   /* just use first order interpolation between data points.  We will       */\
   /* calculate the slope from the present point to the next interpolation   */\
   /* point.                                                                 */\
                                                                               \
   if ( ( i == LAST_SCC_SEGMENT ) || ( i == 0 ) )                              \
   {                                                                           \
      delta = (*pccomp->pprofile)[i+1] - (*pccomp->pprofile)[i];               \
      divisor = N;                                                             \
   }                                                                           \
   else                                                                        \
   {                                                                           \
      delta = (*pccomp->pprofile)[i+1] - (*pccomp->pprofile)[i-1];             \
      divisor = N*2;                                                           \
                                                                               \
   }                                                                           \
                                                                               \
   pccomp->slope         = delta/divisor;                                      \
   pccomp->slope_rem     = (delta%divisor)*(M-1);                              \
   pccomp->slope_rem_sum = pccomp->slope_rem;                                  \
   pccomp->slope_divisor = divisor*(M-1);                                      \
                                                                               \
}                                                                              \


/***********************************************************************/
/* MACRO:  CALC_SCC_2ND_DERIV                                          */
/* ======                                                              */
/*                                                                     */
/* PURPOSE:  To calculate the 2nd derivative between two signal points.*/
/*                                                                     */
/* RETURNED VALUE:  INT32 2nd derivative                               */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:  none                                                        */
/*                                                                     */
/* LIMITATIONS:  This function assumes that the N past to it is        */
/*               non-zero.  If it is called with an N of zero you will */
/*               get a divide by zero.                                 */
/*                                                                     */
/***********************************************************************/

#define CALC_SCC_2ND_DERIV( pccomp, N, M, i )                                  \
{                                                                              \
                                                                               \
   /*********************************************************************/     \
   /*                                                                   */     \
   /* Calculate the 2nd deriv. at a profile data pt. f(i) as follows:   */     \
   /*                                                                   */     \
   /* Second derivative =   f(i+1) - f(i)       f(i) - f(i-1)       1   */     \
   /*                     { ---------------  -  ------------- } * ----- */     \
   /*                            N2                  N1           M - 1 */     \
   /*                                                                   */     \
   /*                      (ave. value of the   (ave. value of the      */     \
   /*                       slope of the ith     slope of the i-1th     */     \
   /*                       segment)             segment)               */     \
   /*                                                                   */     \
   /* where N1 and N2 are the number of signals between f(i-1) and f(i) */     \
   /*       and f(i) and f(i+1)                                         */     \
   /*                                                                   */     \
   /*********************************************************************/     \
                                                                               \
   if ( ( M > 1 ) && ( i < LAST_SCC_SEGMENT ) && ( i != 0 ) )                  \
   {                                                                           \
                                                                               \
      delta =   (*pccomp->pprofile)[i+1] - 2*( (*pccomp->pprofile)[i] )        \
                + (*pccomp->pprofile)[i-1];                                    \
                                                                               \
      divisor = N*(M-1);                                                       \
                                                                               \
      pccomp->deriv2         = delta/divisor;                                  \
      pccomp->deriv2_rem     = delta%divisor;                                  \
      pccomp->deriv2_rem_sum = 0;                                              \
      pccomp->deriv2_divisor = divisor;                                        \
                                                                               \
   }                                                                           \
   else                                                                        \
   {                                                                           \
      /* There is only one subsegment or we are on the first or last segment */\
      /* so we will not be applying a 2nd derivative.                        */\
                                                                               \
      pccomp->deriv2     = 0;                                                  \
      pccomp->deriv2_rem = 0;                                                  \
      pccomp->deriv2_rem_sum = 0;                                              \
      pccomp->deriv2_divisor = 1;                                              \
   }                                                                           \
}                                                                              \




/***********************************************************************/
/* MACRO: HANDLE_TEST_SIGNALS                                          */
/* ======                                                              */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

#define HANDLE_TEST_SIGNALS()                                                  \
{                                                                              \
   switch ( pccomp->type )                                                     \
   {                                                                           \
      case TEST_PLOT_TYPE:                                                     \
                                                                               \
         if ( pccomp->pprofile == ( PROFILE * )TEST_PLOT_PROFILE )             \
         {                                                                     \
            pccomp->pprofile = ( PROFILE * )TEST_PLOT_PROFILE2;                \
         }                                                                     \
         else                                                                  \
         {                                                                     \
            pccomp->pprofile = ( PROFILE * )TEST_PLOT_PROFILE;                 \
            pccomp->scale_factor = pccomp->scale_factor/10;                    \
                                                                               \
            if ( pccomp->scale_factor == 0 )                                   \
            {                                                                  \
               pccomp->scale_factor = INIT_TEST_PLOT_SCALE_FACTOR;             \
            }                                                                  \
                                                                               \
         }                                                                     \
                                                                               \
         pccomp->segment_count = 0;                                            \
         N = pccomp->pdata->Nstd;                                              \
         M = pccomp->pdata->Mstd;                                              \
         i = 0;                                                                \
                                                                               \
         break;                                                                \
                                                                               \
      case TEST_SIGNAL_TYPE:                                                   \
      default:                                                                 \
                                                                               \
         pccomp->segment_count = 0;                                            \
         N = pccomp->pdata->Nstd;                                              \
         M = pccomp->pdata->Mstd;                                              \
         i = 0;                                                                \
                                                                               \
         break;                                                                \
                                                                               \
   }                                                                           \
}



/***********************************************************************/
/* MACRO:  UPDATE_SLOPE_REMAINDER                                      */
/* ======                                                              */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

#define UPDATE_SLOPE_REMAINDER()                                               \
{                                                                              \
                                                                               \
   pccomp->slope_rem_sum += pccomp->slope_rem;                                 \
                                                                               \
   if ( pccomp->slope_rem_sum >= pccomp->slope_divisor )                       \
   {                                                                           \
      pccomp->value += pccomp->scale_factor;                                   \
      pccomp->slope_rem_sum -= pccomp->slope_divisor;                          \
   }                                                                           \
                                                                               \
   if ( pccomp->slope_rem_sum + pccomp->slope_divisor <= 0 )                   \
   {                                                                           \
      pccomp->value -= pccomp->scale_factor;                                   \
      pccomp->slope_rem_sum += pccomp->slope_divisor;                          \
   }                                                                           \
                                                                               \
}



/***********************************************************************/
/* MACRO:  ADD_2ND_DERIV_REMAINDER                                     */
/* ======                                                              */
/*                                                                     */
/* PURPOSE: To add the 2nd derivative remainder value to the remainder */
/*          sum and update the slope if necessary.                     */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

#define ADD_2ND_DERIV_REMAINDER()                                              \
{                                                                              \
   pccomp->deriv2_rem_sum += pccomp->deriv2_rem;                               \
   if ( pccomp->deriv2_rem_sum >= pccomp->deriv2_divisor )                     \
   {                                                                           \
      pccomp->slope++;                                                         \
      pccomp->deriv2_rem_sum -= pccomp->deriv2_divisor;                        \
   }                                                                           \
                                                                               \
   if ( pccomp->deriv2_rem_sum + pccomp->deriv2_divisor <= 0 )                 \
   {                                                                           \
      pccomp->slope--;                                                         \
      pccomp->deriv2_rem_sum += pccomp->deriv2_divisor;                        \
   }                                                                           \
}



/*****************************/
/*   STATIC VARIABLES        */
/*****************************/


/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/

#ifndef mccabe
#pragma ASM
        SECTION.S SysCode
#pragma END_ASM

#pragma SECTION PROG=SysCode
#endif



/***********************************************************************/
/* FUNCTION:  ServiceCompressedSignals                                 */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To expand any selected SCC (signal column compensation)   */
/*           profiles or the compressed test plot and to collect       */
/*           any selected SCC profiles for future use.                 */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:  ExpandSCC, CollectSCC                                       */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

void ServiceCompressedSignals( void )
{
   /*********************************************************************/
   /*                                                                   */
   /* First, filter the front and back detector data so that it is      */
   /* smooth for the scc profile interpolation points.                  */
   /*********************************************************************/

   switch ( DetectorA_Config.type )
   {
      case uECD:  Deta_Data = (INT32)LinUECD( UECD_TBL, Dsp_In.deta_data );
                  break;

      case LDID:  Deta_Data = (INT32)LinLDID( LDID_TBL, Dsp_In.deta_data );
                  break;

      default:    Deta_Data = Dsp_In.deta_data;
   }

   switch ( DetectorB_Config.type )
   {
      case uECD:  Detb_Data = (INT32)LinUECD( UECD_TBL, Dsp_In.detb_data );
                  break;

      case LDID:  Detb_Data = (INT32)LinLDID( LDID_TBL, Dsp_In.detb_data );
                  break;

      default:    Detb_Data = Dsp_In.detb_data;
   }

   FilterSignal32( &Deta_Filt, Deta_Data, ARRAY_SIZE_SCC_DET );
   FilterSignal32( &Detb_Filt, Detb_Data, ARRAY_SIZE_SCC_DET );

   /*********************************************************************/
   /*                                                                   */
   /* The SCC profiles are only applied during the run.  Originally,    */
   /* since they were compensating for changes in the baseline that     */
   /* were caused by changes in the oven temperature they did not start */
   /* applying them until after the oven was done with its initial time.*/
   /* Since we now have programmed pressure and flow that can also      */
   /* effect the baseline we will collect and apply the profile during  */
   /* the entire run.                                                   */
   /* The SCC profiles are only collected when we are in the "SCC Run"  */
   /* state.                                                            */
   /*                                                                   */
   /*********************************************************************/

   /* See if a new run has been started before the SCC run state machine had  */
   /* a chance to transition back to the NOT_IN_RUN state after a STOP.  This */
   /* could happen if there is less than 30 mS between a STOP and a START.    */

   if ( Scc_Start_Pending == TRUE )
   {
      ResetScc();
      Scc_Start_Pending = FALSE;
      Scc_Run_State = RUN_IN_PROGRESS;
   }

   /* Execute column compensation and test plot/signal expansion based upon   */
   /* the Scc_Run_State.  This state machine is used to ensure that the scc   */
   /* signals do not reset to their initial values at the end of a run before */
   /* the signal STOP markers have been sent.  Since the scc data is gener-   */
   /* ated before it is applied to the signals this data cannot reset to its  */
   /* initial conditions until after the signal path has sent the STOP mark-  */
   /* ers.  To delay the reset of the scc profile by one pass through the     */
   /* signal path the StopRun routine sets the Scc_Run_State to STOP_PENDING. */
   /* The scc run state machine then transitions to STOP_PENDING2 without     */
   /* resetting and does not reset until the next time through, when it goes  */
   /* to NOT_IN_RUN.  By this time the signal path will have sent the STOP    */
   /* marker.  NOTE:  This assumes that there will be a minimum time between  */
   /* a START and another start of 120 ms, the width of the APG start pulse.  */

   switch ( Scc_Run_State )
   {
      case RUN_IN_PROGRESS:
         if ((Ccomp1.apply_scc_flag)&&(Ccomp1_Data.data_valid_flag == DATA_OK))
         {
            ExpandSCC( &Ccomp1);
         }

         if ((Ccomp2.apply_scc_flag)&&(Ccomp2_Data.data_valid_flag == DATA_OK))
         {
            ExpandSCC( &Ccomp2);
         }

         if ( Test_Plot.apply_scc_flag )
         {
            ExpandSCC( &Test_Plot );
         }

         if ( Test_Signal.apply_scc_flag )
         {
            ExpandSCC( &Test_Signal );
         }
         break;

      case STOP_PENDING:
            Scc_Run_State = STOP_PENDING2;
            break;

      case STOP_PENDING2:
            ResetScc();
            Scc_Run_State = NOT_IN_RUN;
            break;

      case NOT_IN_RUN:
            break;
   }

   /* Check to see if we are in a SCC_RUN where we will be collect-  */
   /* ing one or two SCC profiles.                                   */

   if ( Scc_Run && (Run_State == RUN_ACTIVE) )
   {
      /* See if scc collect selected */
      if ( Ccomp1.collect_scc_flag )
      {
         CollectSCC( &Ccomp1 );
      }

      if ( Ccomp2.collect_scc_flag )
      {
         CollectSCC( &Ccomp2 );
      }
   }
}



/***********************************************************************/
/* FUNCTION:  CollectSCC                                               */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To collect an SCC profile.  This function will keep track */
/*           of time and store a signal value if necessary.            */
/*                                                                     */
/* RETURNED VALUE:  none                                               */
/*                                                                     */
/* GLOBALS USED:  SCC profile 1:  Ccomp1 and Ccomp1_Data -or-          */
/*                SCC profile 2:  Ccomp2 and Ccomp2_Data               */
/*                                                                     */
/* CALLS:  none                                                        */
/*                                                                     */
/* LIMITATIONS:  It is assumed that this function is called at the     */
/*               same frequency as the signal path:  100 Hz.           */
/*                                                                     */
/***********************************************************************/

void CollectSCC( pCCOMP_TABLE pccomp )
{

   /* See if we should collect a data point */
   if ( pccomp->signal_count == 0 )
   {

      /* Get the next data point from the signal DSP detector out signal.*/
      /* This data comes at a 100 Hz rate, so it is perfect for us to  */
      /* use for the SCC profile collection which is done at 100 Hz.   */

      if ( pccomp->pdata->det_data_stored == FRONT )
      {
         (*pccomp->pprofile)[pccomp->segment_count] = Deta_Filt.filt_out.output;
      }
      else
      {
         (*pccomp->pprofile)[pccomp->segment_count] = Detb_Filt.filt_out.output;
      }

      /* See if we just finished processing the segment of the SCC profile */
      /* If so, then we are done collecting so we will disable the collect */
      /* SCC flag.                                                         */

      if ( pccomp->segment_count >= LAST_SCC_SEGMENT+1 )
      {
         /* Flag that there is now a valid SCC profile */
         pccomp->pdata->data_valid_flag  = DATA_OK;
      }
      else
      {
         /* See if we are NOW on the "extra" segment.  This last segment will */
         /* have a different number of data points in it from the rest.       */

         if ( pccomp->segment_count == LAST_SCC_SEGMENT )
         {
            /* If the last segment, which is really an "extra" segment has    */
            /* a signal count, Nlast, of zero then we are done with the       */
            /* profile, otherwise set the segment count to Nlast and continue.*/

            if ( pccomp->pdata->Nlast == 0 )
            {
               /* Flag that there is now a valid SCC profile */
               pccomp->pdata->data_valid_flag  = DATA_OK;
            }
            else
            {
               pccomp->signal_count = pccomp->pdata->Nlast - 1;
            }

         }
         else
         {
            pccomp->signal_count = pccomp->pdata->Nstd - 1;
         }

         pccomp->segment_count++;  /* increment ptr to next available data pt */

      }
   }
   else
   {
      /* Decrement signal count for the segment we are processing */
      pccomp->signal_count--;
   }

}



/***********************************************************************/
/* FUNCTION:  ExpandSCC                                                */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To calculate the next data point for the enabled          */
/*           column compensation profile(s) and the test plot.         */
/*                                                                     */
/* RETURNED VALUE:  none                                               */
/*                                                                     */
/* GLOBALS USED:  Ccomp1, Ccomp2:  working values for scc 1,2          */
/*                Ccomp1_Data, Ccomp2_Data:  scc profiles 1,2          */
/*                                                                     */
/* CALLS:  CALC_SCC_SLOPE, CALC_SCC_2ND_DERIV                          */
/*                                                                     */
/* LIMITATIONS:  This function runs during the 512 Hz interrupt so     */
/*               it must be fast.  Thus all function calls are avoided */
/*               to eliminate the overhead associated with them.       */
/*                                                                     */
/***********************************************************************/

void ExpandSCC( pCCOMP_TABLE pccomp )
{
   U_INT16 N;       /* # of signal pt.s per segment */
   U_INT16 M;       /* # of subsegments per segment */
   INT32   delta;
   INT32   divisor;
   U_INT8  i;


   i = pccomp->segment_count;

   /* Check to see if we are done with the scc profile.  The algorithm is */
   /* forgiving in that it allows you to increase the final time without  */
   /* having to re-run the column compensation run. If we are done with   */
   /* expanding the profile then we will do nothing, assuming that the    */
   /* last value calculated will be used.                                 */

   if ( i <= LAST_SCC_SEGMENT+1 )
   {

      /* Get the number of signal points per segment and number of        */
      /* subsegments per segment.  There is a possible "extra" segment if */
      /* the segments do not divide up evenly.                            */

      if ( i >= LAST_SCC_SEGMENT )
      {
         N = pccomp->pdata->Nlast;
         M = pccomp->pdata->Mlast;
      }
      else
      {
         N = pccomp->pdata->Nstd;
         M = pccomp->pdata->Mstd;
      }

      /* First, see if we are at the beginning of a subsegment.  If so, */
      /* then we will update the slope with the 2nd derivative.         */

      if ( pccomp->signal_count == 0 )
      {
         /* Init count for # of signals processed within a subsegment. */
         pccomp->signal_count = NO_OF_SIGNALS_PER_SUBSEGMENT;

         /* Decrement down-counting subsegment counter */
         pccomp->subsegment_count--;

         /* Now take into consideration the fractional remainder from  */
         /* the 2nd derivative calculation before updating the slope.  */

         /* Update slope by adding in 2nd derivative */
         pccomp->slope += pccomp->deriv2;
         ADD_2ND_DERIV_REMAINDER();

      }

      /* Is this the beginning of a segment?  If so, then are we done with */
      /* the profile?                                                      */

      if ( pccomp->subsegment_count == 0 )
      {
         /* See if we are finished with a test profile.  If so, then set   */
         /* the pointer to the beginning of the next appropriate test      */
         /* profile.  We will continue repeating the test profile sequence */
         /* until the run is STOPPED.                                      */

         if ( pccomp->segment_count == LAST_SCC_SEGMENT )
         {
            HANDLE_TEST_SIGNALS();
         }

         /* Test to see if the next segment is valid.  If it has a non-    */
         /* zero number of signals per segment then we will continue       */

         if ( ( i <= LAST_SCC_SEGMENT ) && ( N != 0 ) )
         {
            /* Initialize down-counting subsegment counter */
            pccomp->subsegment_count = M;

            /*  Initialize down-counting signal counter  */
            pccomp->signal_count = NO_OF_SIGNALS_PER_SUBSEGMENT;

            /* Calculate slope */
            CALC_SCC_SLOPE( pccomp,N,i );

            /* Calculate the 2nd derivative */
            CALC_SCC_2ND_DERIV( pccomp,N,M,i );

            /* Assign the value to the interpolation data pt minus the    */
            /* initial value.                                             */

            if ( pccomp == &Test_Plot )
            {
               pccomp->value = (*pccomp->pprofile)[i] * pccomp->scale_factor;
            }
            else
            {
               /* Generate the new compensation data point */

               /* Add the slope to the previous value to get the new value. */
               pccomp->value += pccomp->slope*pccomp->scale_factor;
            }
         }
         else     /* we are done with the profile so set the slope to zero */
         {
            pccomp->slope     = 0;
            pccomp->slope_rem = 0;
         }

         /* Increment segment counter */
         pccomp->segment_count++;

      }
      else
      {
         /* Generate the new compensation data point */

         /* First, take into consideration the fractional remainder of the */
         /* slope value.                                                   */
         UPDATE_SLOPE_REMAINDER();

         /* Next add the slope to the previous value to get the new value. */
         pccomp->value += pccomp->slope*pccomp->scale_factor;

      }

      /* Decrement count for # of signals processed within a subsegment */
      pccomp->signal_count--;
   }
}



/***********************************************************************/
/* FUNCTION:  ApplySCC                                                 */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To modify the signal(s) appropriately by applying SCC     */
/*           or test plot values.                                      */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* CALLS:  none                                                        */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

void ApplySCC( pDIG_DATA psig )
{
   switch ( pSignal->ccomp_mode )
   {
      case ADD_CCOMP1:
         psig->hi_long = Ccomp1.value;
         psig->lo_word = 0;
         break;

      case ADD_CCOMP2:
         psig->hi_long = Ccomp2.value;
         psig->lo_word = 0;
         break;

      case SUBTRACT_CCOMP1:

         /* Apply Ccomp1 value to the MS 2-bytes         */
         /* Subtract Ccomp1.value and check for overflow */
         SUBTRACT_AND_CLAMP( psig->hi_long, Ccomp1.value );
         break;

      case SUBTRACT_CCOMP2:

         /* Apply Ccomp2 value to the MS 2-bytes         */
         /* Subtract Ccomp2.value and check for overflow */
         SUBTRACT_AND_CLAMP( psig->hi_long, Ccomp2.value );
         break;

      case EXPAND_TEST_PLOT:

         psig->hi_long = Test_Plot.value;
         psig->lo_word = 0;
         break;

      case EXPAND_TEST_SIGNAL:
      default:
         psig->hi_long = Test_Signal.value;
         psig->lo_word = 0;

   }
}

INT32 ApplySCC_32( INT32 s_signal )
{
   switch ( pSignal->ccomp_mode )
   {
      case ADD_CCOMP1:
         return( Ccomp1.value );

      case ADD_CCOMP2:
         return( Ccomp2.value );

      case SUBTRACT_CCOMP1:

         /* Subtract Ccomp1.value and check for overflow */
         SUBTRACT_AND_CLAMP( s_signal, Ccomp1.value );
         return( s_signal );

      case SUBTRACT_CCOMP2:

         /* Subtract Ccomp2.value and check for overflow */
         SUBTRACT_AND_CLAMP( s_signal, Ccomp2.value );
         return( s_signal );

      case EXPAND_TEST_PLOT:

         return( Test_Plot.value );

      case EXPAND_TEST_SIGNAL:
      default:

         return( Test_Signal.value );
   }
}

#pragma SECTION UNDO
